using MultiAgentsClient.ChatDataStructures;
using MultiAgentsShared;
using static MultiAgentsClient.Manager.ProjectManager;
using static MultiAgentsClient.Manager.UserInfoManager;

namespace MultiAgentsClient.Presentation;

public partial record ChatRoomListModel
{
    private readonly IEventBus eventBus;

    public IListState<ChatProjectDisp> ChatProjectsDisp => ListState<ChatProjectDisp>.Empty(this);
    public IState<string> NewChatRoomName => State.Value(this, () => "");
    public int SelectedMentionableIndex = 0;
    public IState<int> SelectedChatRoomId => State.Value(this, () => 0);

    public record CreateProjectClickCommand();

    public ChatRoomListModel()
    {
        eventBus = EventBus.Instance;

        eventBus.Subscribe<FetchUserdataCompletedCommand>(async cmd => { await FetchUserdataCompletedCommandHandler(cmd); });
        eventBus.Subscribe<CreateProjectCompleteCommand>(async cmd => { await CreateProjectCompletedEvent(cmd); });
        eventBus.Subscribe<DeleteProjectCompleteCommand>(async cmd => { await DeleteProjectCompleteCommandHandler(cmd); });
        eventBus.Subscribe<CreateChatRoomCompleteCommand>(async cmd => { await CreateChatRoomCompletedEvent(cmd); });
        eventBus.Subscribe<SwitchChatRoomCompleteCommand>(async cmd => { await SwitchChatRoomCompletedEvent(cmd); });
        eventBus.Subscribe<RenameChatRoomCompleteCommand>(async cmd => { await RenameChatRoomCompletedEvent(cmd); });
        eventBus.Subscribe<ArchiveChatRoomCompleteCommand>(async cmd => { await ArchiveChatRoomCompletedEvent(cmd); });
        eventBus.Subscribe<DeleteChatRoomCompleteCommand>(async cmd => { await DeleteChatRoomCompletedEvent(cmd); });
    }

    public void CreateProject()
    {
        eventBus.Publish(new CreateProjectClickCommand());
    }

    public void OpenProjectSettings(int targetProjectId)
    {
        eventBus.Publish(new FetchProjectSettingsCommand(targetProjectId));
    }

    public void CreateChatRoom(int projectIdIn)
    {
        eventBus.Publish(new CreateChatRoomCommand(projectIdIn, "新聊天室"));
    }

    public void SwitchChatRoom(int chatRoomIdIn)
    {
        eventBus.Publish(new SwitchChatRoomCommand(chatRoomIdIn));
    }

    public void ArchiveChatRoom(int chatRoomId)
    {
        eventBus.Publish(new ArchiveChatRoomCommand(chatRoomId));
    }

    public void DeleteChatRoom(int chatRoomId)
    {
        eventBus.Publish(new DeleteChatRoomCommand(chatRoomId));
    }

    public async ValueTask RenameChatRoom(int chatRoomId)
    {
        string? newChatRoomName = await NewChatRoomName;
        if (string.IsNullOrEmpty(newChatRoomName))
        {
            return;
        }

        await NewChatRoomName.SetAsync("");
        eventBus.Publish(new RenameChatRoomCommand(chatRoomId, newChatRoomName));
    }

    public async ValueTask ChatRoomListExpanderClicked(int projectId)
    {
        ChatProjectDisp toggledProject = (await ChatProjectsDisp).First(p => p.Id == projectId).ToggleExpanded();

        await ChatProjectsDisp.UpdateAsync(toggledProject);
    }

    #region commands
    private async ValueTask FetchUserdataCompletedCommandHandler(FetchUserdataCompletedCommand initViewEvent)
    {
        UserDataModel userData = initViewEvent.UserData;
        await ChatProjectsDisp.RemoveAllAsync(match: item => true);
        foreach (ChatProject chatProject in userData.chatProjects)
        {
            await ChatProjectsDisp.AddAsync(chatProject.ToDisp(userData.selectedChatRoomId));
        }
    }

    private async ValueTask CreateProjectCompletedEvent(CreateProjectCompleteCommand prjCreatedEvent)
    {
        await ChatProjectsDisp.AddAsync(prjCreatedEvent.ChatPrjDisp);
    }

    private async Task DeleteProjectCompleteCommandHandler(DeleteProjectCompleteCommand cmd)
    {
        await ChatProjectsDisp.RemoveAllAsync(match: item => item.Id == cmd.ProjectId);
    }

    private async ValueTask CreateChatRoomCompletedEvent(CreateChatRoomCompleteCommand roomCreatedEvent)
    {
        await ChatProjectsDisp.UpdateAsync(
            match: cp => cp.Id == roomCreatedEvent.ChatPrjDisp.Id,
            updater: cp => roomCreatedEvent.ChatPrjDisp,
            default
        );
    }

    private async ValueTask RenameChatRoomCompletedEvent(RenameChatRoomCompleteCommand renameEvent)
    {
        await ChatProjectsDisp.UpdateAllAsync(
                match: item => item.Id == renameEvent.ProjectId,
                updater: cp => cp.RenameChatRoom(renameEvent.ChatRoomId, renameEvent.ChatRoomName)
                );
    }

    private async ValueTask SwitchChatRoomCompletedEvent(SwitchChatRoomCompleteCommand cmd)
    {
        int selectedChatRoomId = cmd.ChatRoomId;

        await SelectedChatRoomId.SetAsync(selectedChatRoomId);

        if (cmd.ChatMessageDisps == null)
        {
            return;
        }

        // Default Chat Room GPT typrId 1
        SelectedMentionableIndex = 0;

        await ChatProjectsDisp.Update(updater: cp =>
        {
            var updatedList = cp.Select(prj => prj.UpdateSelectedChatRoom(selectedChatRoomId)).ToImmutableList();
            return updatedList;
        }, default);
    }

    private async ValueTask ArchiveChatRoomCompletedEvent(ArchiveChatRoomCompleteCommand archiveEvent)
    {
        await ChatProjectsDisp.UpdateAsync(
            match: cp => cp.Id == archiveEvent.ChatPrjDisp.Id,
            updater: cp => archiveEvent.ChatPrjDisp,
            default
        );
    }

    private async ValueTask DeleteChatRoomCompletedEvent(DeleteChatRoomCompleteCommand deleteEvent)
    {
        await ChatProjectsDisp.UpdateAsync(
            match: cp => cp.Id == deleteEvent.ChatPrjDisp.Id,
            updater: cp => deleteEvent.ChatPrjDisp,
            default
        );
    }
    #endregion
}
